#ifndef VTKPATHWRITER_HH
#define VTKPATHWRITER_HH

#include <cstdlib>
#include <cstdio>
#include <cstring>
#include "Types.hh"
#include <vector>
#include "Debug.hh"
#include <iostream>
#include <stdlib.h>

class VTKPathWriter
{
public:

	VTKPathWriter(const std::vector< int > &dimension,
		const std::vector< real >& length, const std::string &problem)
		:mDim(dimension)
	{
		INFO("*****************************************************");
		INFO("Setting output to file: "<<problem);
		INFO("************`para*****************************************");

		std::string filename = problem;
		filename += ".vtk";
		problem1 = filename;
		//std::cout << filename <<std::endl;
		mStream = fopen(filename.c_str(), "w");

		if ( mStream == NULL )
		{
			ERROR("Error opening outputfile");
		}

		fprintf( mStream, "# vtk DataFile Version 4.0\n");
		fprintf( mStream, "HESP -Molecular Dynamics- Visualization%s\n",problem.c_str());
		fprintf( mStream, "ASCII\n");
		fprintf( mStream, "DATASET UNSTRUCTURED_GRID\n");    
	}

	~VTKPathWriter( )
	{
		fprintf( mStream, "\n" );
		fclose(mStream);
	}

	void WriteVector(const std::vector< std::vector< real > > &vec,
		const std::string &name)
	{
		INFO("*****************************************************");
		INFO("Register Vector: "<<name<<" with dimension "<<vec.size());
		INFO("*****************************************************");

		fprintf( mStream, "VECTORS %s double\n", name.c_str()); // Check how to print the String here!

		switch( vec.size() )
		{
		case 2:
			for(int i=0, end = vec[0].size(); i<end; i++)
			{
				for(int dim=0, iend=vec.size(); dim<iend; dim++)
				{
					fprintf( mStream, "%f ", vec[dim][i]);
				}
				fprintf( mStream, " 0\n ");
			}
			break;

		case 3:
			for(int i=0, end = vec[0].size(); i<end; i++)
			{
				for(int dim=0, iend=vec.size(); dim<iend; dim++)
				{
					fprintf( mStream, "%f ", vec[dim][i]);
				}
				fprintf( mStream, "\n ");
			}
			break;
		default:
			std::cout << "Unsupported dimension" << vec.size()<< std::endl;
			ERROR("Unsupported Dimension "<<vec.size());
		}
	}



	cl_float4* Pos = (cl_float4*)CmdQ.enqueueMapBuffer(PosBuffer, true, CL_MAP_WRITE, 0, 
		N * sizeof(cl_float4));

	cl_float latticeWidth = BOXLENGTH / CUBE_ROOT_N;
	//Generates positions on a simple cubic lattice
	for (size_t partID(0); partID < N; ++partID)
	{
		Pos[partID][0] = latticeWidth * (partID % CUBE_ROOT_N) 
			- (BOXLENGTH / 2.0);
		Pos[partID][1] = latticeWidth * ((partID / CUBE_ROOT_N) % CUBE_ROOT_N)
			- (BOXLENGTH / 2.0);
		Pos[partID][2] = latticeWidth * ((partID / (CUBE_ROOT_N * CUBE_ROOT_N)) % CUBE_ROOT_N)
			- (BOXLENGTH / 2.0);
		Pos[partID][3] = 0.0;
	}




	void WriteFloat4(const cl_float *Pos, const size_t N, const std::string &name)
	{
		INFO("*****************************************************");
		INFO("Register Vector: "<<name<<" with dimension "<<vec.size());
		INFO("*****************************************************");

		fprintf( mStream, "VECTORS %s double\n", name.c_str()); // Check how to print the String here!


		for (size_t partID(0); partID < N; ++partID)
		{
				fprintf( mStream, "%f   %f   %f ", Pos[partID][0], Pos[partID][1], Pos[partID][2]);
		}
	}


	void VTKFileWriter::WriteScalar(const std::vector<real>& scalar,
		const  std::string& name)
	{
		INFO("*****************************************************");
		INFO("Register Scalar: "<<name);
		INFO("*****************************************************");

		fprintf( mStream, "SCALARS %s double 1\n",name.c_str() );
		fprintf( mStream, "LOOKUP_TABLE default\n");

		for(int i=0, end=scalar.size(); i<end; i++)
		{
			fprintf( mStream, "%f\n", scalar[i] );
		}
	}
private:

	FILE *mStream;
	std::vector< int > mDim;
	std::string problem1;
};
#endif // VTKPATHWRITER_HH



